#ifndef _PART2D_CACHE_H_
#define _PART2D_CACHE_H_

#include "part2d.h"
#include "num/named_set.h"


/*
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Part2D Cache Container
// ======================
//
// Use to minimize the hit on the hard disk and cache memory allocation
//
// Usage:
// Call GetPart to load a particle and receive a Part2D pointer
// To destroy the particle, call Release (recommended) or delete it manually (not recommended)
// You can preload and allocate a set of particles on game start by passing PreallocateOnly = true in GetPart
//
// Cache Size:
// Use SetMinCacheSize to set the # of elements that the cache will preallocate whenever the cache is empty
// or
// Pass a CustomCacheSize in GetPart to individually customize preallocation units on a per-particle basis
//
// Notes:
// Part2D pointers returned by the cache are NOT meant to be manipulated (e.g. adding new forces, changing gen rates, etc)
// -- if you do, manually delete the pointer when you're done and DON'T return it to the cache via Release
// -- otherwise, weird shit will happen
//
// If your singleton class (init using static Instance()) is using this cache, it is recommended to delete particles manually rather than Release in the destructor
*/

namespace part2d
{

class Part2DCache
{
public:
	struct PART_CACHE
	{
		Part2D					Part;
		unsigned int			CustomCacheSize;
		std::vector<Part2D*>	Cache;
		bool					IsValid;
	};

	static Part2DCache&		Instance();

	Part2D*					GetPart(const std::string& File, unsigned int CustomCacheSize = 0, bool PreallocateOnly = false);
	void					Release(Part2D* pPart);

	void					SetMinCacheSize(unsigned int i) { m_MinCacheSize = i; }
	void					CacheFolder(const std::string& Folder = "effects", unsigned int CustomCacheSize = 0);

private:
	Part2DCache();
	virtual ~Part2DCache();

	PART_CACHE*				CreateNewElement(const std::string& Name, unsigned int CustomCacheSize = 0);
	void					PreallocateCache(PART_CACHE* pCache, unsigned int ForceMin = 0);
	
	num::NamedSet<PART_CACHE*>	m_Cache;
	unsigned int				m_MinCacheSize;
};

}; //part2d


#define PART_CACHE()		part2d::Part2DCache::Instance()
#define RELEASE_PART(x)		{ if (x) PART_CACHE().Release(x); x = NULL; }


#endif //_PART2D_CACHE_H_
